home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr25 / me310.zip / UE310C.ZIP / ST520.C < prev    next >
C/C++ Source or Header  |  1989-03-18  |  23KB  |  933 lines

  1. /*    ST520:    Atari ST1040/520 support functions
  2.         written by lots of people (see below)
  3.  
  4.         Daniel Lawrence
  5.         James Turner
  6.         Jeff Lomicka
  7.         J. C. Benoist
  8.  
  9.     Modification History:
  10.     31-dec-87    Jeff Lomicka
  11.     - massive changes/additions for accessories and mouse
  12.     20-jan-87    Daniel Lawrence
  13.     - changed code in domousekey() to pass five bytes, two zeros
  14.       (to tell input.c that this is a mouse event), x/ypos
  15.       and the mouse event type.
  16.     may 88        Jeff Lomicka and Dan Lawrence
  17.     - a lot of changes.  Through out aline.h, use the MWC and
  18.       ATARI names for things now.
  19.     - moving the mouse to the extreme upper left brings up
  20.       the desk accessory menu.  EMACS won't replot on the
  21.       way out yet.
  22.     - cleaned up behavior of the mouse and the cursor on exit
  23.     26-feb-89    Daniel Lawrence
  24.     - rewote input layer to conform to new specs in input.c
  25. */
  26.  
  27. #define termdef 1        /* don't define "term" external */
  28.  
  29. #include    <stdio.h>
  30. #include    "estruct.h"
  31. #include    "etype.h"
  32. #include    "edef.h"
  33. #include    "elang.h"
  34.  
  35. #if    ATARI & ST520
  36.  
  37. /*
  38.     These routines provide support for the ATARI 1040ST and 520ST
  39. using the virtual VT52 Emulator
  40.  
  41. */
  42.  
  43. #include    <aesbind.h>
  44. #include    <gemdefs.h>
  45. #include    <obdefs.h>
  46. #include    <osbind.h>
  47. #include    <xbios.h>
  48. #include    <linea.h>
  49.  
  50. #define NROW    50    /* Screen size.         */
  51. #define NCOL    80    /* Edit if you want to.     */
  52. #define MARGIN    8    /* size of minimim margin and    */
  53. #define SCRSIZ    64    /* scroll size for extended lines */
  54. #define NPAUSE    300    /* # times thru update to pause */
  55. #define BIAS    0x20    /* Origin 0 coordinate bias.    */
  56. #define ESC    0x1B    /* ESC character.        */
  57. #define SCRFONT 2    /* index of 8x16 monochrome system default font */
  58. #define DENSIZE 50    /* # of lines in a dense screen */
  59.  
  60. /****    ST Internals definitions        *****/
  61.  
  62. /*    BIOS calls */
  63.  
  64. #define BCONSTAT    1    /* return input device status */
  65. #define CONIN        2    /* read character from device */
  66. #define BCONOUT     3    /* write character to device */
  67.  
  68. /*    XBIOS calls */
  69.  
  70. #define INITMOUS    0    /* initialize the mouse     */
  71. #define GETREZ        4    /* get current resolution    */
  72. #define SETSCREEN    5    /* set screen resolution    */
  73. #define SETPALETTE    6    /* set the color pallette    */
  74. #define SETCOLOR    7    /* set or read a color        */
  75. #define CURSCONF    21    /* set cursor configuration    */
  76. #define IKBDWS        25    /* intelligent keyboard send command */
  77. #define KBDVBASE    34    /* get keyboard table base    */
  78.  
  79. /*    GEMDOS calls */
  80.  
  81. #define EXEC        0x4b    /* Exec off a process */
  82. #define CON        2    /* CON: Keyboard and screen device */
  83.  
  84. /*    Palette color definitions    */
  85.  
  86. #define LOWPAL    "000700070770007707077777333733373773337737377777"
  87. #define MEDPAL    "000700007777"
  88. #define HIGHPAL "111000"
  89.  
  90. /*    ST Global definitions        */
  91.  
  92. int initrez;            /* initial screen resolution */
  93. int currez;            /* current screen resolution */
  94. int gemflag;            /* were we called from the desktop? */
  95. int mouseon;            /* True if mouse is on */
  96. char resname[][8] = {        /* screen resolution names */
  97.     "LOW", "MEDIUM", "HIGH", "DENSE"
  98. };
  99. short spalette[16];        /* original color palette settings */
  100. short palette[16];        /* current palette settings */
  101. static short scursor;        /* original text cursor mode */
  102.  
  103. struct la_data *aline;        /* Line A data structure */
  104.  
  105. struct la_ext *naline;        /* extended Line A data structure */
  106.  
  107. struct la_font **fonts;    /* Array of pointers to the three system
  108.               font headers returned by init (in register A1) */
  109.  
  110. struct la_font *system_font;    /* pointer to default system font */
  111. struct la_font *small_font;    /* pointer to small font */
  112.  
  113. /*
  114.     These are needed to make GEM happy
  115. */
  116. int contrl[ 11], intin[ 128], intout[ 128], ptsin[ 256], ptsout[ 12];
  117. static int worki[ 11] = {1,1,1,1,1,1,1,1,1,1,2}, worko[ 57];
  118.  
  119. /*
  120.     Some useful information about our environment
  121. */
  122. static int
  123.     g_wchar, g_hchar,    /* VDI's idea of current font size */
  124.     junk, gid, wkid;    /* Graphics ID, workstation ID */
  125.  
  126. static int oldbut = 0;        /* Previous state of mouse buttons */
  127. static int mctrl;        /* current BEG_MOUSE state */
  128.  
  129. /*
  130.     This object tree is for displaying the desk accessory menu.
  131.     Actual positions are written into this structure when the
  132.     screen size is known.
  133. */
  134. OBJECT menu[] =
  135.     {
  136.     -1, 1, 4,    G_IBOX,   NONE,  NORMAL, 0x0L,        0 , 0,   0,   0,/* Root */
  137.      4, 2, 2,     G_BOX,   NONE,  NORMAL, 0x10F0L,   0,    0,   1,   1,/* BAR */
  138.      1, 3, 3,    G_IBOX,   NONE,  NORMAL, 0x0L,        0,    0,   1,   1,/* Active */
  139.      2,-1,-1,  G_TITLE,   NONE,  NORMAL,  "",        0,    0,   1,   1,/* title */
  140.      0, 5, 5,    G_IBOX,   NONE,  NORMAL, 0x0L,        0,    0,   0,   0,/* screen */
  141.      4, 6,13,     G_BOX,   NONE,  NORMAL, 0xFF1100L, 0,    0,   0,   0,/* box */
  142.      7,-1,-1, G_STRING,   NONE,  NORMAL, TEXT179,0,0,168,    16,
  143. /*                                       "  About MicroEmacs" */
  144.      8,-1,-1, G_STRING,   NONE,DISABLED, "---------------------",
  145.                             0, 16, 168,  16,
  146.      9,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 32, 168,  16,
  147.     10,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 48, 168,  16,
  148.     11,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 64, 168,  16,
  149.     12,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 80, 168,  16,
  150.     13,-1,-1, G_STRING,   NONE,  NORMAL, "",        0, 96, 168,  16,
  151.      5,-1,-1, G_STRING, LASTOB,  NORMAL, "",        0,112, 168,  16
  152.     };
  153.  
  154. extern mymouse();        /* .s file for calling two mouse handlers */
  155. int (*first_mhandler)();    /* Address of first handler */
  156. int (*second_mhandler)();    /* Address of second handler */
  157. struct kbdvbase *kv;        /* Keyboard vector table */
  158. static int msevntsiz = 0;    /* Events in private mouse event queue */
  159. static unsigned short msevntq[16];/* State of mouse keys at event */
  160. static int msevntin = 0;    /* Queue input ptr */
  161. static int msevntout = 0;    /* Queue output ptr */
  162. static int mousekeys1 = 0;    /* Last mouse key event */
  163. static int mousecol = HUGE;    /* current mouse column */
  164. static int mouserow = HUGE;    /* current mouse row */
  165.  
  166. extern    int    ttopen();        /* Forward references.        */
  167. extern    int    ttgetc();
  168. extern    int    ttputc();
  169. extern    int    ttflush();
  170. extern    int    ttclose();
  171. extern    int    stmove();
  172. extern    int    steeol();
  173. extern    int    steeop();
  174. extern    int    stbeep();
  175. extern    int    stopen();
  176. extern    int    stclose();
  177. extern    int    stgetc();
  178. extern    int    stputc();
  179. extern    int    strev();
  180. extern    int    strez();
  181. extern    int    stkopen();
  182. extern    int    stkclose();
  183.  
  184. #if    COLOR
  185. extern    int    stfcol();
  186. extern    int    stbcol();
  187. #endif
  188.  
  189. /*
  190.  * Dispatch table. All the
  191.  * hard fields just point into the
  192.  * terminal I/O code.
  193.  */
  194. TERM    term    = {
  195.     NROW-1,
  196.     NROW-1,
  197.     NCOL,
  198.     NCOL,
  199.     MARGIN,
  200.     SCRSIZ,
  201.     NPAUSE,
  202.     &stopen,
  203.     &stclose,
  204.     &stkopen,
  205.     &stkclose,
  206.     &stgetc,
  207.     &stputc,
  208.     &ttflush,
  209.     &stmove,
  210.     &steeol,
  211.     &steeop,
  212.     &stbeep,
  213.     &strev,
  214.     &strez
  215. #if    COLOR
  216.     , &stfcol,
  217.     &stbcol
  218. #endif
  219. };
  220.  
  221. /*    input buffers and pointers    */
  222.  
  223. #define    IBUFSIZE    64    /* this must be a power of 2 */
  224.  
  225. unsigned char in_buf[IBUFSIZE];    /* input character buffer */
  226. int in_next = 0;        /* pos to retrieve next input character */
  227. int in_last = 0;        /* pos to place most recent input character */
  228.  
  229. in_init()    /* initialize the input buffer */
  230.  
  231. {
  232.     in_next = in_last = 0;
  233. }
  234.  
  235. in_check()    /* is the input buffer non-empty? */
  236.  
  237. {
  238.     if (in_next == in_last)
  239.         return(FALSE);
  240.     else
  241.         return(TRUE);
  242. }
  243.  
  244. in_put(event)
  245.  
  246. int event;    /* event to enter into the input buffer */
  247.  
  248. {
  249.     in_buf[in_last++] = event;
  250.     in_last &= (IBUFSIZE - 1);
  251. }
  252.  
  253. int in_get()    /* get an event from the input buffer */
  254.  
  255. {
  256.     register int event;    /* event to return */
  257.  
  258.     event = in_buf[in_next++];
  259.     in_next &= (IBUFSIZE - 1);
  260.     return(event);
  261. }
  262.  
  263. void init_aline()
  264.  
  265. {
  266.     int *ld_contrl;
  267.     int *ld_intin;
  268.  
  269.     linea0();
  270.  
  271.     /* save if the current mouse is hidden (ie we are not in GEM) */
  272.     gemflag = (mousehidden == 0);
  273.     while (mousehidden) {
  274.         showmouse();
  275.         }
  276.     aline = (struct la_data *)(la_init.li_a0);
  277.     fonts = (struct la_font **)(la_init.li_a1);
  278.     naline = ((struct la_ext *)aline) - 1;
  279.     scursor = naline->ld_status;        /* State of text cursor */
  280.     ld_contrl = aline->ld_contrl;        /* -> control junk    */
  281.     ld_intin  = aline->ld_intin;        /* -> intin junk    */
  282. }
  283.  
  284. init()
  285.  
  286. {
  287.     init_aline();
  288.     system_font = fonts[SCRFONT];        /* save it */
  289.     small_font = fonts[1];
  290. }
  291.  
  292.  
  293. switch_font(fp)
  294.  
  295. struct la_font *fp;
  296.  
  297. {
  298.        /* See linea.h for description of fields */
  299.  
  300.        V_CEL_HT = fp->font_height;
  301.        V_CEL_WR = aline->ld_vwrap * fp->font_height;
  302.        V_CEL_MY = (naline->ld_y_max / fp->font_height) - 1;
  303.        V_CEL_MX = (naline->ld_x_max / fp->font_fat_cell) - 1;
  304.        V_FNT_WR = fp->font_width;
  305.        V_FNT_ST = fp->font_low_ade;
  306.        V_FNT_ND = fp->font_hi_ade;
  307.        V_OFF_AD = (long) fp->font_char_off;
  308.        V_FNT_AD = (long) fp->font_data;
  309. }
  310.  
  311. stmove(row, col)
  312.  
  313. {
  314.     stputc(ESC);
  315.     stputc('Y');
  316.     stputc(row+BIAS);
  317.     stputc(col+BIAS);
  318. }
  319.  
  320. steeol()
  321.  
  322. {
  323.     stputc(ESC);
  324.     stputc('K');
  325. }
  326.  
  327. steeop()
  328.  
  329. {
  330. #if    COLOR
  331.     stfcol(gfcolor);
  332.     stbcol(gbcolor);
  333. #endif
  334.     stputc(ESC);
  335.     stputc('J');
  336. }
  337.  
  338. strev(status)    /* set the reverse video state */
  339.  
  340. int status;    /* TRUE = reverse video, FALSE = normal video */
  341.  
  342. {
  343.     if (currez > 1) {
  344.         stputc(ESC);
  345.         stputc(status ? 'p' : 'q');
  346.     }
  347. }
  348.  
  349. #if    COLOR
  350. mapcol(clr)    /* medium rez color translation */
  351.  
  352. int clr;    /* emacs color number to translate */
  353.  
  354. {
  355.     static int mctable[] = {0, 1, 2, 3, 2, 1, 2, 3};
  356.  
  357.     if (currez != 1)
  358.         return(clr);
  359.     else
  360.         return(mctable[clr]);
  361. }
  362.  
  363. stfcol(color)    /* set the forground color */
  364.  
  365. int color;    /* color to set forground to */
  366.  
  367. {
  368.     if (currez < 2) {
  369.         stputc(ESC);
  370.         stputc('b');
  371.         stputc(mapcol(color));
  372.     }
  373. }
  374.  
  375. stbcol(color)    /* set the background color */
  376.  
  377. int color;    /* color to set background to */
  378.  
  379. {
  380.     if (currez < 2) {
  381.         stputc(ESC);
  382.         stputc('c');
  383.         stputc(mapcol(color));
  384.     }
  385. }
  386. #endif
  387.  
  388. static char beep[] = {
  389.     0x00, 0x00,
  390.     0x01, 0x01,
  391.     0x02, 0x01,
  392.     0x03, 0x01,
  393.     0x04, 0x02,
  394.     0x05, 0x01,
  395.     0x07, 0x38,
  396.     0x08, 0x10,
  397.     0x09, 0x10,
  398.     0x0A, 0x10,
  399.     0x0B, 0x00,
  400.     0x0C, 0x30,
  401.     0x0D, 0x03,
  402.     0xFF, 100,
  403.     0x09, 0x00,
  404.     0x0A, 0x00,
  405.     0xFF, 0x00
  406. };
  407.  
  408. stbeep()
  409.  
  410. {
  411.     Dosound(beep);
  412. }
  413.  
  414. mouse_on()    /* turn the gem mouse ON */
  415.  
  416. {
  417.     if (!mouseon) {
  418.         graf_mouse( M_ON, 0L);
  419.         graf_mouse(ARROW, 0L);
  420.         mouseon = 1;
  421.     }
  422. }
  423.  
  424. mouse_off()    /* turn the gem mouse OFF */
  425.  
  426. {
  427.     if (mouseon) {
  428.         graf_mouse( M_OFF, 0L);
  429.         mouseon = 0;
  430.     }
  431.     if( !mousehidden) stbeep();
  432. }
  433.  
  434. /*
  435.     me_mh - MicroEmacs Mouse interrupt Handler.  This handler is called,
  436.     in addition to the regular mouse handler, in order for microemacs
  437.     to have access to some more information about the mouse events.
  438.  
  439.     What it does is:
  440.  
  441.     - Queue a copy of the mouse button state at the actual moment of
  442.     the event, rather than after GEM is finished playing with timers.
  443.  
  444.     - Convert all right-mouse-button events into left-mouse-button
  445.     events BEFORE GEM's mouse interrupt handler, so that GEM will generate
  446.     a left-mouse-button event.
  447. */
  448. me_mh(a)
  449.  
  450. char *a;
  451. {
  452.     register unsigned mousekeys;
  453.     
  454.     mousekeys = a[0] & 7;
  455.     if (mousekeys != 0)
  456.         a[0] = 0xFA;     /* Any key down means button 1 down */
  457.     else
  458.         a[0] = 0xf8;    /* Otherwise button 1 up */
  459.     if (msevntsiz < 16) {
  460.         /* Previous event was processed, look for next one */
  461.         if (mousekeys != mousekeys1) {
  462.             /* A button change is detected, insert it in queue */
  463.             msevntq[msevntin++] = mousekeys;
  464.             msevntin &= 15;
  465.             msevntsiz++;
  466.             mousekeys1 = mousekeys;
  467.         }
  468.     }
  469. }
  470.  
  471.  
  472. stkopen()    /* open the keyboard (and mouse) */
  473. {
  474. }
  475.  
  476. stopen()    /* open the screen */
  477.  
  478. {
  479.     register int i;
  480.  
  481.     init();
  482.  
  483. /*
  484.     Set up an interrupt handler for the mouse that performs both
  485.     me_mh() and the default mouse handling.  The .s file "stmouse.s"
  486.     contains some special code for this purpose.
  487. */
  488.     first_mhandler = me_mh;
  489.     kv = Kbdvbase();
  490.     second_mhandler = kv->kb_mousevec;
  491.     kv->kb_mousevec = mymouse;
  492. /*
  493.     In order to have both the mouse cursor and the text cursor on the
  494.     screen at the same time, we have to flash it ourselves, turning
  495.     the mouse cursor on and off for each flash.
  496.  
  497.     The cursors are both off whenever we are not in an input wait.
  498. */
  499.     Cursconf(3, 0);    /* Stop text cursor from flashing */   
  500.     Cursconf(0, 0);    /* Turn text cursor off */
  501. /*
  502.     Wake up GEM and the VDI
  503. */
  504.     appl_init();
  505.     gid = graf_handle(&g_wchar, &g_hchar, &junk, &junk);
  506. #if    0
  507.     /* We never use the VDI, but if you do, turn this back on */
  508.     v_opnvwk(worki, &wkid, worko);
  509. #endif
  510.     graf_mouse( M_OFF, 0L);
  511.     mouseon = 0;
  512. /*
  513.     Set up the menu bar's coordinates to match the font and screen size
  514.     for this screen resolution
  515. */
  516.     wind_get(0, WF_CURRXYWH,    /* Fetch actual screen size for menu */
  517.         &menu[0].ob_x, &menu[0].ob_y,
  518.         &menu[0].ob_width, &menu[0].ob_height);
  519.     menu[1].ob_x = menu[0].ob_width - 1;    /* Locate "desk" box */
  520.     menu[4].ob_width = menu[0].ob_width;
  521.     menu[4].ob_height = 8*g_hchar;
  522.     menu[5].ob_width = 21*g_wchar;
  523.     menu[5].ob_height = 8*g_hchar;
  524.     menu[5].ob_x = menu[0].ob_width - menu[5].ob_width;
  525.     for(i=6; i<14; i++) {
  526.         /* Desk accessory items */
  527.         menu[i].ob_y = (i-6)*g_hchar;
  528.         menu[i].ob_width = menu[5].ob_width;
  529.         menu[i].ob_height = g_hchar;
  530.     }
  531.     menu_bar(menu, 1);
  532. /*
  533.     Shut off GEM's user interface until we enter an input wait.
  534.     Note that unless we claim the mouse with BEG_MCTRL, we will not
  535.     get scheduled to run any time the left mouse button goes down while
  536.     the mouse is on the top 16 pixels of the screen.  We keep Emacs
  537.     "hung" whenever MCTRL is given to desk accessories or GEM, and keep
  538.     GEM hung whenever we have control.
  539. */
  540.     wind_update(BEG_UPDATE);    /* Shuts off GEM drawing */
  541.     wind_update(BEG_MCTRL);        /* Shuts off GEM use of mouse */
  542.  
  543.     mctrl = 0;            /* Flag that we have mouse control */
  544.  
  545.     ttopen();
  546.     eolexist = TRUE;
  547.  
  548.     /* save the current color palette */
  549.     for (i=0; i<16; i++)
  550.         spalette[i] = xbios(SETCOLOR, i, -1);
  551.  
  552.     /* and find the current resolution */
  553.     initrez = currez = xbios(GETREZ);
  554.     strcpy(sres, resname[currez]);
  555.  
  556.     /* set up the screen size and palette */
  557.     switch (currez) {
  558.         case 0: term.t_mrow = 25 - 1;
  559.             term.t_nrow = 25 - 1;
  560.             term.t_ncol = 40;
  561.             strcpy(palstr, LOWPAL);
  562.             break;
  563.  
  564.         case 1: term.t_mrow = 25 - 1;
  565.             term.t_nrow = 25 - 1;
  566.             strcpy(palstr, MEDPAL);
  567.             break;
  568.  
  569.         case 2: term.t_mrow = DENSIZE - 1;
  570.             term.t_nrow = 25 - 1;
  571.             strcpy(palstr, HIGHPAL);
  572.     }
  573.  
  574.     /* and set up the default palette */
  575.     spal(palstr);
  576.  
  577.     stputc(ESC);    /* automatic overflow off */
  578.     stputc('w');
  579.  
  580.     /* initialize the input buffer */
  581.     in_init();
  582. }
  583.  
  584. stkclose()    /* close the keyboard (and mouse) */
  585. {
  586. }
  587.  
  588. stclose()
  589.  
  590. {
  591.     stputc(ESC);    /* auto overflow on */
  592.     stputc('v');
  593.  
  594.     /* restore the original screen resolution */
  595.     if (currez == 3)
  596.         switch_font(system_font);
  597.     strez(resname[initrez]);
  598.  
  599.     /* restore the original palette settings */
  600.     xbios(SETPALETTE, spalette);
  601.  
  602.     ttclose();
  603.  
  604.     kv->kb_mousevec = second_mhandler;    /* Restore original handler */
  605.  
  606.     mouse_on();        /* turn the mouse on */
  607.     if (gemflag != 0) {
  608.         /* coming from gem..... we */
  609.         Cursconf(0, 0);        /* turn the cursor off */
  610.     } else {
  611.         /* coming from a shell, we */
  612.         Cursconf(1, 0);        /* turn the cursor on */
  613.         Cursconf(2, 0);        /* Turn text cursor blinking */
  614.         hidemouse();        /* Turn mouse off for shell */
  615.     }
  616.  
  617.     wind_update(END_MCTRL);        /* Return GEM's control of screen */
  618.     wind_update(END_UPDATE);
  619. #if    0
  620.     v_clsvwk(wkid);            /* Clean up GEM */
  621. #endif
  622.     appl_exit();
  623. }
  624.  
  625. /*    spal(pstr):    reset the current palette according to a
  626.             "palette string" of the form
  627.  
  628.     000111222333444555666777
  629.  
  630.     which contains the octal values for the palette registers
  631. */
  632.  
  633. spal(pstr)
  634.  
  635. char *pstr;    /* palette string */
  636.  
  637. {
  638.     int pal;    /* current palette position */
  639.     int clr;    /* current color value */
  640.     int i;
  641.  
  642.     for (pal = 0; pal < 16; pal++) {
  643.         if (*pstr== 0)
  644.             break;
  645.  
  646.         /* parse off a color */
  647.         clr = 0;
  648.         for (i = 0; i < 3; i++)
  649.             if (*pstr)
  650.                 clr = clr * 16 + (*pstr++ - '0');
  651.         palette[pal] = clr;
  652.     };
  653.  
  654.     /* and now set it */
  655.     xbios(SETPALETTE, palette);
  656. }
  657.  
  658. static domousekey(newbut, sk)
  659.  
  660. int sk;
  661.  
  662. {
  663.     register int k;
  664.  
  665.     for(k=1; k!=4; k = k<<1) {    /* J is butnum, k is bit num */ 
  666.         /* For each button on the mouse */
  667.         if ((oldbut&k) != (newbut&k)) {
  668.             /* This button changed, generate an event */
  669.             in_put(0);        /* escape indicator */
  670.             in_put(MOUS >> 8);    /* mouse event */
  671.             in_put(mousecol);    /* x-position */
  672.             in_put(mouserow);    /* y-position */
  673.             in_put(((newbut&k) ? 0 : 1)
  674.                 + (k==1 ? 4 : 0)
  675.                 + ((sk&3) ? 'A' : 'a'));
  676.         }
  677.     }
  678.     oldbut = newbut;
  679. }
  680.  
  681. stgetc()    /* get a char from the keyboard */
  682.  
  683. {
  684.     register int flashcounter;    /* Counter for flashing cursor */
  685.     register int ev_which;        /* Event returned */
  686.     register int sc;        /* Keyboard scan code */
  687.     static int bexpected = 1;    /* Expected next mouse state */
  688.     int mx, my, bstate, sk, key, mc;/* Event parameters */
  689.     int mes[8];
  690.  
  691.     /* Working out a multi-byte input sequence */
  692.     if (in_check())
  693.         return(in_get());
  694.  
  695.     Cursconf(1, 0);        /* Turn text cursor on */
  696.     mouse_on();        /* Let mouse work */
  697.     wind_update(END_UPDATE);
  698.     if (mctrl)
  699.         wind_update(END_MCTRL);
  700.     flashcounter = 0;
  701.     for(;;) {
  702.         if (!mctrl) {
  703.             /* We have control, so it is okay to flash cursor */
  704.             if (flashcounter == 6) {
  705.                 mouse_off();
  706.                 Cursconf(0, 0); /* After 60ms, turn it off */
  707.                 mouse_on();
  708.             } else if (flashcounter == 10) {
  709.                 /* Wrapped around one cycle of cursor flashing,
  710.                    turn it on */
  711.                 mouse_off();
  712.                 Cursconf(1, 0);
  713.                 mouse_on();
  714.                 flashcounter = 0;
  715.             }
  716.         }
  717.  
  718.         /* do the event-multi thing */
  719.         ev_which = evnt_multi(
  720.             MU_TIMER | MU_MESAG | MU_KEYBD | MU_BUTTON | MU_M1,
  721.             1,        /* Maximum clicks to wait for */
  722.             1,        /* Buttons that generate events */
  723.             bexpected,    /* Button states that generate events */
  724.             0, menu[1].ob_x, menu[1].ob_y,
  725.             menu[1].ob_width, menu[1].ob_height,
  726.             0, 0, 0, 0, 0,    /* enter/exit, x, y, w, h for rect 2 */
  727.             mes,        /* Buffer to receive mesasge */
  728.             /* Low and high order miliseconds of counter */
  729.             100, 0,
  730.             &mx, &my,    /* Mouse location */
  731.             &bstate,    /* State of the mouse buttons */
  732.             &sk,        /* State of the shift keys */
  733.             &key,        /* Key pressed */
  734.             &mc);        /* Actual number of clicks */
  735.  
  736.         if (ev_which & MU_KEYBD) {
  737.             /* Keyboard events cause keystrokes, add SPC prefix to fn keys */
  738.             if (mctrl)
  739.                 wind_update(BEG_MCTRL);
  740.             Giaccess(0, 9+128);
  741.             Giaccess(0, 10+128);
  742.  
  743.             /* Cancel any double-clicking */
  744.             nclicks = 0;
  745.             mctrl = 0;
  746.  
  747.                  sc = key>>8;
  748.                 key &= 0xff;
  749.  
  750.                 /* a keycode of 0 indicates an extended char code */
  751.                 if (key == 0) {
  752.                     key = extcode(sc);
  753.                     in_put(0);    /* escape indicator */
  754.                     in_put(key >> 8);/* key type */
  755.                     in_put(key & 255);/* key code */
  756.                 } else {
  757.                 in_put(key);
  758.             }
  759. #if    0
  760.                 if ((sc>=0x63 && sc<=0x72) || sc == 0x4a || sc == 0x4e) {
  761.                 /* This is a keypad key, apply FN prefix to it */
  762.                 in_put(0);        /* excape indicator */
  763.                 in_put(SPEC >> 8);    /* function key */
  764.                 in_put(key);    /* code of this key */
  765.             }
  766. #endif
  767.         } else if (ev_which & MU_BUTTON) {
  768.             /* Mouse event, look at our actual mouse event */
  769.             int top, junk;
  770.             wind_get(0, WF_TOP, &top, &junk, &junk, &junk);
  771.             if (top == 0) {
  772.                 /* Desktop is top window,
  773.                    allow Emacs to continue */
  774.                 bexpected = (~bstate)&1;
  775.                 mousecol = mx/g_wchar;
  776.                 mouserow = my/g_hchar;
  777.                 while(msevntsiz > 0) {
  778.                     /* Process each queued event */
  779.                     domousekey(msevntq[msevntout++], sk);
  780.                     msevntout &= 15;
  781.                     msevntsiz--;
  782.                     }
  783.                 if (mctrl) wind_update(BEG_MCTRL);
  784.                 mctrl = 0;
  785.             }
  786.         } else if (ev_which & MU_M1) {
  787.             /* Mouse entered desk menu, allow it to appear */
  788.             if (!mctrl) wind_update(END_MCTRL);
  789.             mctrl = 1;
  790.             sgarbf = TRUE;
  791.         } else if (ev_which & MU_TIMER) {
  792.             flashcounter++;
  793.         } else {
  794.             /* Most likely is the about message */
  795.         }
  796.  
  797.         /* is there now a pending event? */
  798.         if (in_check()) {
  799.             key = in_get();
  800.             break;
  801.         }
  802.     }
  803.  
  804.     if (mctrl)
  805.         wind_update(BEG_MCTRL);
  806.     wind_update(BEG_UPDATE);
  807.     mouse_off();
  808.     Cursconf(0, 0);            /* Turn text cursor off */
  809.     return(key & 0xFF);
  810. }
  811.  
  812. stputc(c)    /* output char c to the screen */
  813.  
  814. char c;     /* character to print out */
  815.  
  816. {
  817.     bios(BCONOUT, CON, c);
  818. }
  819.  
  820. strez(newrez)    /* change screen resolution */
  821.  
  822. char *newrez;    /* requested resolution */
  823.  
  824. {
  825.     int nrez;    /* requested new resolution */
  826.  
  827.     /* first, decode the resolution name */
  828.     for (nrez = 0; nrez < 4; nrez++)
  829.         if (strcmp(newrez, resname[nrez]) == 0)
  830.             break;
  831.     if (nrez == 4) {
  832.         mlwrite(TEXT180);
  833. /*                      "%%No such resolution" */
  834.         return(FALSE);
  835.     }
  836.  
  837.     /* next, make sure this resolution is legal for this monitor */
  838.     if ((currez < 2 && nrez > 1) || (currez > 1 && nrez < 2)) {
  839.         mlwrite(TEXT181);
  840. /*                      "%%Resolution illegal for this monitor" */
  841.         return(FALSE);
  842.     }
  843.  
  844.     /* eliminate non-changes */
  845.     if (currez == nrez)
  846.         return(TRUE);
  847.  
  848.     /* finally, make the change */
  849.     switch (nrez) {
  850.         case 0: /* low resolution - 16 colors */
  851.             newwidth(TRUE, 40);
  852.             strcpy(palstr, LOWPAL);
  853.             xbios(SETSCREEN, -1L, -1L, 0);
  854.             g_wchar = g_hchar = 8;
  855.             break;
  856.  
  857.         case 1: /* medium resolution - 4 colors */
  858.             newwidth(TRUE, 80);
  859.             strcpy(palstr, MEDPAL);
  860.             xbios(SETSCREEN, -1L, -1L, 1);
  861.             g_wchar = g_hchar = 8;
  862.             break;
  863.  
  864.         case 2: /* High resolution - 2 colors - 25 lines */
  865.             newsize(TRUE, 25);
  866.             strcpy(palstr, HIGHPAL);
  867.             switch_font(system_font);
  868.             g_wchar = g_hchar = 16;
  869.             break;
  870.  
  871.         case 3: /* Dense resolution - 2 colors - 40 lines */
  872.             newsize(TRUE, DENSIZE);
  873.             strcpy(palstr, HIGHPAL);
  874.             switch_font(small_font);
  875.             g_wchar = g_hchar = 8;
  876.             break;
  877.     }
  878.  
  879.     /* and set up the default palette */
  880.     spal(palstr);
  881.     currez = nrez;
  882.     strcpy(sres, resname[currez]);
  883.  
  884.     stputc(ESC);    /* automatic overflow off */
  885.     stputc('w');
  886.     return(TRUE);
  887. }
  888.  
  889. #if    LATTICE
  890. system(cmd)    /* call the system to execute a new program */
  891.  
  892. char *cmd;    /* command to execute */
  893.  
  894. {
  895.     char *pptr;            /* pointer into program name */
  896.     char pname[NSTRING];        /* name of program to execute */
  897.     char tail[NSTRING];        /* command tail */
  898.  
  899.     /* scan off program name.... */
  900.     pptr = pname;
  901.     while (*cmd && (*cmd != ' ' && *cmd != '\t'))
  902.         *pptr++ = *cmd++;
  903.     *pptr = 0;
  904.  
  905.     /* create program name length/string */
  906.     tail[0] = strlen(cmd);
  907.     strcpy(&tail[1], cmd);
  908.  
  909.     /* go do it! */
  910.     return(gemdos(        (int)EXEC,
  911.                 (int)0,
  912.                 (char *)pname,
  913.                 (char *)tail,
  914.                 (char *)NULL));
  915. }
  916. #endif
  917.  
  918. #if    FLABEL
  919. fnclabel(f, n)        /* label a function key */
  920.  
  921. int f,n;    /* default flag, numeric argument [unused] */
  922.  
  923. {
  924.     /* on machines with no function keys...don't bother */
  925.     return(TRUE);
  926. }
  927. #endif
  928. #else
  929. sthello()
  930. {
  931. }
  932. #endif
  933.